#include <assert.h>
#include <stdio.h>

#include "../src/estep.c"

typedef struct _EStepTestDatum EStepTestDatum;
struct _EStepTestDatum
{ 
  struct
    {
      float     loga[6 * 4];
      float     logbeta;
      float     c[6 * 5];
      float     d[6 * 5];
      float     priorz[5];
      int       clamp;
      Rating    ratings[8];
    }                   inputs;

  float pz[5];
};

static void
test_estep (void)
{
  EStepTestDatum data[] = 
    {{{{0.911763, 0.500117, 0.699389, 0.329142, 0.985051, 0.516042,    0.938806, 0.935321, 0.765739, 0.558145, 0.591284, 0.33837,    0.573122, 0.620202, 0.0472319, 0.208222, 0.627871, 0.825239,    0.941384, 0.847438, 0.36827, 0.485378, 0.582958, 0.564539},   0.456507, {0.985261, 0.883569, 0.235397, 0.471456, 0.469219,    0.944763, 0.300076, 0.705717, 0.911074, 0.353479, 0.961707,    0.132594, 0.290872, 0.306247, 0.753485, 0.504723, 0.465633,    0.364862, 0.906046, 0.136454, 0.980255, 0.781904, 0.341508,    0.679947, 0.994993, 0.898335, 0.106111, 0.208491, 0.525774,    0.953572}, {0.806034, 0.502774, 0.6147, 0.600094, 0.844328,    0.37018, 0.323828, 0.293847, 0.090843, 0.865456, 0.858195,    0.928985, 0.184797, 0.729002, 0.877941, 0.147081, 0.843289,    0.0490559, 0.882947, 0.248746, 0.737178, 0.840565, 0.357173,    0.295174, 0.931144, 0.337791, 0.742473, 0.69508, 0.0868161,    0.967612}, {0.418645, 0.401233, 0.995973, 0.102156,    0.560449}, -1, {{0, 0}, {0, 4}, {3, 2}, {0, 0}, {0, 2}, {1,     2}, {1, 3}, {3, 2}}}, {7.43594e-12, 1.87668e-13, 1.,   4.36384e-12,   1.65276e-11}}, {{{0.811176, 0.373153, 0.682509, 0.325168,    0.967887, 0.324097, 0.799561, 0.076422, 0.230709, 0.483532,    0.442388, 0.781248, 0.299565, 0.145741, 0.699915, 0.0861684,    0.212749, 0.178129, 0.281271, 0.684935, 0.216776, 0.0759734,    0.720821, 0.212687},   0.405599, {0.70282, 0.0383128, 0.887519, 0.437712, 0.378723,    0.238752, 0.811097, 0.207003, 0.895191, 0.796363, 0.029849,    0.907438, 0.749451, 0.0964477, 0.943681, 0.694689, 0.571322,    0.815177, 0.258745, 0.477913, 0.495348, 0.0943556, 0.0460582,    0.0723141, 0.792528, 0.0560429, 0.158539, 0.634602, 0.413805,    0.817291}, {0.347441, 0.427599, 0.518614, 0.0209282, 0.317592,    0.520161, 0.769163, 0.92448, 0.373912, 0.825472, 0.197841,    0.109303, 0.115166, 0.347558, 0.702493, 0.0149478, 0.0691082,    0.275244, 0.909965, 0.958905, 0.910569, 0.640642, 0.49616,    0.141614, 0.563128, 0.213043, 0.977547, 0.120685, 0.245536,    0.692882}, {0.208384, 0.196205, 0.871624, 0.86741,    0.0105423}, -1, {{1, 1}, {1, 0}, {2, 4}, {1, 4}, {2, 2}, {2,     1}, {3, 2}, {1, 1}}}, {0.000169797, 0.999599, 0.000181084,   2.56852e-6,   0.0000476186}}, {{{0.756458, 0.519852, 0.308049, 0.0719537,    0.68735, 0.244608, 0.398084, 0.113049, 0.77678, 0.603966,    0.901924, 0.971435, 0.213652, 0.390923, 0.924377, 0.85075,    0.968116, 0.69804, 0.715993, 0.654545, 0.0964919, 0.83063,    0.705451, 0.567643},   0.340034, {0.310778, 0.397402, 0.49569, 0.652684, 0.0661702,    0.999318, 0.382641, 0.875904, 0.462205, 0.0973942, 0.411206,    0.662252, 0.0712819, 0.173017, 0.560456, 0.694136, 0.373241,    0.457024, 0.905911, 0.597644, 0.542611, 0.751573, 0.338268,    0.25761, 0.231833, 0.354171, 0.842579, 0.604925, 0.165663,    0.354853}, {0.459938, 0.729021, 0.703458, 0.257459, 0.0487322,    0.0667695, 0.632177, 0.0844419, 0.488276, 0.372634, 0.258935,    0.627418, 0.582365, 0.77499, 0.716324, 0.875845, 0.244097,    0.51738, 0.484491, 0.521674, 0.401518, 0.912455, 0.318828,    0.16682, 0.94158, 0.183434, 0.615369, 0.909361, 0.892848,    0.116664}, {0.983193, 0.824919, 0.404572, 0.74403,    0.724257}, -1, {{3, 4}, {1, 2}, {1, 0}, {1, 0}, {2, 2}, {1,     2}, {1, 4}, {0, 2}}}, {9.94507e-7, 5.74255e-13, 0.999938,   2.14318e-10,   0.0000605906}}, {{{0.822207, 0.96904, 0.00793347, 0.321657,    0.57811, 0.45166, 0.523443, 0.799983, 0.176592, 0.539205,    0.204615, 0.633163, 0.235013, 0.355771, 0.589246, 0.723802,    0.342165, 0.239107, 0.606053, 0.898883, 0.937593, 0.495077,    0.881796, 0.701381},   0.115386, {0.526036, 0.873862, 0.379725, 0.537276, 0.0743766,    0.35042, 0.579742, 0.360684, 0.535172, 0.145805, 0.946579,    0.125671, 0.179401, 0.556559, 0.222777, 0.783506, 0.940294,    0.950505, 0.323894, 0.845913, 0.445217, 0.0687095, 0.622513,    0.730527, 0.919181, 0.194847, 0.242788, 0.193251, 0.844804,    0.844427}, {0.663046, 0.832567, 0.309632, 0.698623, 0.716467,    0.706896, 0.130231, 0.142064, 0.49369, 0.92339, 0.189938,    0.191559, 0.169796, 0.0774768, 0.744721, 0.122849, 0.547283,    0.34695, 0.82554, 0.928002, 0.304495, 0.153699, 0.980736,    0.0835749, 0.641448, 0.321132, 0.671104, 0.384952, 0.924981,    0.614236}, {0.540873, 0.242888, 0.431291, 0.690846,    0.350935}, -1, {{0, 4}, {0, 0}, {0, 4}, {3, 2}, {2, 3}, {1,     3}, {1, 2}, {1, 4}}}, {0.0000164239, 1.6525e-7, 0.00387232,   0.000249363,   0.995862}}, {{{0.261495, 0.61337, 0.606214, 0.92848, 0.714212,    0.266419, 0.780674, 0.00047801, 0.409717, 0.11272, 0.799937,    0.916903, 0.768269, 0.791588, 0.128833, 0.531951, 0.843288,    0.177352, 0.58796, 0.289063, 0.411998, 0.486505, 0.237026,    0.237733},   0.150503, {0.873136, 0.630812, 0.309253, 0.436291, 0.606716,    0.850138, 0.308775, 0.026574, 0.493996, 0.0502006, 0.391872,    0.258305, 0.702408, 0.921367, 0.859921, 0.415017, 0.525057,    0.333407, 0.570858, 0.00301941, 0.0385515, 0.0963812, 0.333125,    0.852516, 0.165416, 0.46557, 0.0238717, 0.416225, 0.5587,    0.615432}, {0.715097, 0.389651, 0.0647034, 0.565231, 0.323224,    0.131346, 0.362295, 0.643864, 0.463303, 0.716329, 0.837238,    0.310457, 0.892445, 0.71331, 0.798687, 0.214076, 0.55932,    0.860793, 0.633271, 0.748506, 0.535449, 0.444568, 0.0745716,    0.133074, 0.820352, 0.0549168, 0.00986821, 0.567843, 0.497128,    0.923571}, {0.647573, 0.92398, 0.0338242, 0.207241, 0.810335},   3, {{3, 0}, {0, 3}, {1, 1}, {3, 2}, {1, 1}, {0, 1}, {3, 3}, {1,     0}}}, {0.0000153263, 0.00872824, 2.28441e-6, 0.991254,   3.62902e-8}}, {{{0.141379, 0.493932, 0.011648, 0.399447,    0.582059, 0.633138, 0.378377, 0.650941, 0.0466102, 0.18857,    0.303805, 0.517867, 0.226258, 0.133653, 0.293937, 0.950023,    0.729131, 0.210083, 0.646364, 0.0260436, 0.695306, 0.00284153,    0.836029, 0.412521},   0.553927, {0.50891, 0.824381, 0.0130738, 0.971868, 0.875772,    0.446004, 0.362133, 0.925258, 0.687201, 0.142199, 0.844266, 0.699,     0.553548, 0.848262, 0.894243, 0.96987, 0.343465, 0.201898,    0.868199, 0.274563, 0.340623, 0.365869, 0.455679, 0.720636,    0.831714, 0.541488, 0.442605, 0.748768, 0.955942,    0.0954834}, {0.0804719, 0.823509, 0.268741, 0.953285, 0.236206,    0.124509, 0.715193, 0.105023, 0.341962, 0.154639, 0.371728,    0.903125, 0.473763, 0.880076, 0.0311043, 0.537257, 0.0180844,    0.15944, 0.199391, 0.995769, 0.57548, 0.410673, 0.243449,    0.900286, 0.495008, 0.587163, 0.974708, 0.947001, 0.258802,    0.462654}, {0.259516, 0.841978, 0.91684, 0.308015, 0.887788},   1, {{2, 3}, {3, 4}, {1, 2}, {2, 3}, {1, 3}, {1, 4}, {1, 4}, {0,     0}}}, {2.97032e-6, 0.0751156, 0.0000674925, 0.0652307,   0.859583}}, {{{0.443077, 0.427939, 0.856684, 0.401596, 0.424992,    0.268499, 0.657293, 0.405827, 0.849513, 0.857826, 0.413844,    0.505541, 0.354505, 0.270663, 0.439135, 0.55854, 0.0957025,    0.808008, 0.17962, 0.716562, 0.178863, 0.499994, 0.291832,    0.777709},   0.735786, {0.0720549, 0.435148, 0.376113, 0.310793, 0.803556,    0.777855, 0.970286, 0.461281, 0.94573, 0.364011, 0.464745,    0.106776, 0.675068, 0.924876, 0.906206, 0.0110735, 0.867059,    0.745256, 0.189644, 0.832211, 0.367066, 0.453425, 0.411935,    0.096425, 0.295011, 0.0182765, 0.0358226, 0.785632, 0.491454,    0.240421}, {0.0655365, 0.324351, 0.545724, 0.87641, 0.600791,    0.217575, 0.870656, 0.951534, 0.694586, 0.206501, 0.00359713,    0.206278, 0.504942, 0.37429, 0.636532, 0.752853, 0.0930065,    0.277865, 0.341521, 0.734577, 0.0571839, 0.492234, 0.850067,    0.494155, 0.991647, 0.167883, 0.304343, 0.617745, 0.390856,    0.950308}, {0.433686, 0.666212, 0.69627, 0.743807,    0.430089}, -1, {{1, 0}, {1, 2}, {3, 0}, {3, 2}, {0, 3}, {3,     4}, {3, 3}, {0, 2}}}, {0.0204981, 8.57959e-11, 0.979239,   0.000262824,   1.51519e-8}}, {{{0.191329, 0.369517, 0.793558, 0.707081,    0.098322, 0.0916518, 0.452037, 0.972504, 0.0411381, 0.599418,    0.60197, 0.478349, 0.0494907, 0.431535, 0.297628, 0.860604,    0.658635, 0.481226, 0.863941, 0.194392, 0.962364, 0.737419,    0.433852, 0.734458},   0.771036, {0.367902, 0.640295, 0.0273771, 0.672714, 0.27625,    0.188258, 0.0548726, 0.631576, 0.676832, 0.586288, 0.576523,    0.582085, 0.245297, 0.28866, 0.71592, 0.92345, 0.764071, 0.424719,     0.521528, 0.961086, 0.0266519, 0.990867, 0.78707, 0.19005,    0.65875, 0.350572, 0.759692, 0.517337, 0.382499,    0.162314}, {0.70482, 0.885761, 0.705667, 0.576026, 0.128296,    0.303676, 0.46037, 0.287365, 0.412377, 0.380226, 0.696298,    0.862646, 0.890849, 0.419139, 0.669647, 0.87178, 0.103779,    0.229089, 0.0108968, 0.521208, 0.344087, 0.711753, 0.628397,    0.358894, 0.639267, 0.825992, 0.92273, 0.782869, 0.510971,    0.522316}, {0.462361, 0.495503, 0.0985943, 0.14209, 0.766062},   1, {{1, 4}, {2, 4}, {3, 3}, {1, 0}, {2, 4}, {2, 1}, {0, 3}, {3,     1}}}, {1.87255e-7, 0.992431, 1.1186e-11, 0.0000332585,   0.00753518}}, {{{0.207745, 0.722951, 0.0964158, 0.761077, 0.103966,     0.493862, 0.0855189, 0.239869, 0.759879, 0.782109, 0.457121,    0.880974, 0.120612, 0.956117, 0.534391, 0.0981058, 0.609641,    0.433802, 0.0720302, 0.602603, 0.511047, 0.291711, 0.305968,    0.969746},   0.303301, {0.56876, 0.209552, 0.208669, 0.199335, 0.0748987,    0.124033, 0.9688, 0.439456, 0.29279, 0.666912, 0.0878258,    0.318844, 0.336672, 0.132521, 0.98972, 0.709203, 0.902871,    0.0604904, 0.387117, 0.198157, 0.61116, 0.754522, 0.417371,    0.894855, 0.0423992, 0.54497, 0.208702, 0.69552, 0.967501,    0.420937}, {0.239902, 0.256064, 0.674711, 0.754025, 0.152076,    0.937219, 0.338039, 0.621505, 0.162356, 0.228016, 0.435168,    0.561015, 0.775239, 0.0298595, 0.824008, 0.806492, 0.357868,    0.135004, 0.781609, 0.261522, 0.149165, 0.439484, 0.814109,    0.840584, 0.909263, 0.183421, 0.139398, 0.086559, 0.757187,    0.246201}, {0.801359, 0.465054, 0.59483, 0.0181852, 0.366191},   3, {{0, 4}, {3, 0}, {1, 3}, {2, 4}, {2, 4}, {1, 0}, {1, 3}, {3,     2}}}, {2.07208e-6, 3.29908e-12, 6.35452e-8, 0.999848,   0.000149586}}, {{{0.819591, 0.988326, 0.542183, 0.0975475,    0.461723, 0.853321, 0.760574, 0.836026, 0.312558, 0.413837,    0.946465, 0.995441, 0.403295, 0.230416, 0.807067, 0.908882,    0.646108, 0.984215, 0.00570813, 0.443828, 0.0512781, 0.96603,    0.639517, 0.539789},   0.231687, {0.977704, 0.0973341, 0.442241, 0.769964, 0.124383,    0.33676, 0.606215, 0.457406, 0.710546, 0.390295, 0.610774,    0.0541108, 0.48013, 0.583228, 0.701892, 0.408002, 0.495915,    0.57752, 0.258063, 0.356724, 0.529885, 0.938003, 0.718274,    0.125037, 0.552181, 0.840669, 0.276033, 0.355073, 0.427798,    0.503909}, {0.669818, 0.897668, 0.717252, 0.113613, 0.0590438,    0.843557, 0.237122, 0.530385, 0.357152, 0.435554, 0.741208,    0.952865, 0.0990891, 0.0788302, 0.211323, 0.0148617, 0.380815,    0.953793, 0.659142, 0.174193, 0.104782, 0.59872, 0.231344,    0.670284, 0.434964, 0.701052, 0.514093, 0.556671, 0.37592,    0.857495}, {0.27697, 0.026286, 0.0187679, 0.42194,    0.535763}, -1, {{2, 1}, {1, 1}, {1, 2}, {0, 0}, {3, 3}, {1,     2}, {1, 0}, {2, 0}}}, {0.720742, 0.25033, 0.0289016,   0.0000240599, 1.95545e-6}}};

  for (unsigned int i = 0; i < sizeof (data) / sizeof (data[0]); ++i)
    {
      float pz[5];

      for (unsigned int j = 0; j < 5; ++j) { pz[j] = drand48 (); }

      estep (data[i].inputs.loga,
             6,
             data[i].inputs.logbeta,
             data[i].inputs.c,
             5,
             data[i].inputs.d,
             pz,
             data[i].inputs.priorz,
             data[i].inputs.clamp,
             data[i].inputs.ratings,
             8);

      for (unsigned int j = 0; j < 5; ++j)
        {
          assert (fabs (pz[j] - data[i].pz[j]) <=
                  1e-4 * (1 + fabs (pz[j]) + fabs (data[i].pz[j])) ||
                  (fprintf (stderr, "%u %u (%d): %g ?= %g\n", i, j, data[i].inputs.clamp, pz[j], data[i].pz[j]), 0));
        }
    }
}

int 
main (void)
{
  srand48 (69);

  test_estep ();

  return 0;
}
